DMMF: 集約
Order(注文)と OrderLine(注文明細行)について
注文の詳細は時間とともに変わるが、同じ注文
時間とともに数量や価格が変更されても、依然として同じ注文明細
ある注文明細行を変更した場合、その明細行が属する注文も変更したことになる?
イミュータブルな Order がイミュータブルな OrderLine のコレクションを持っている場合
Order 全体に変更を加える必要がある
擬似コード
code:fsharp
// order: トップレベルの注文
// orderLineId: 変更したい注文明細行の ID
// newPrice: 新しい価格
let changeOrderLinePrice = order orderLineId newPrice =
// 1. orderLine を用いて変更する行を検索
let orderLine = order.OrderLines |> findOrderLine.orderLineId
// 2. 新しい価格を持つ明細行を作成
let newOrderLine = { orderLine with Price = newPrice }
// 3. 古い明細行を新しい明細行で置き換えた、新しい明細行リストを作成
let newOrderLines =
order.OrderLines |> replaceOrderLine orderLineId newOrderLine
// 4. 古い明細行リストを新しい明細行リストで置き換えた、新しい注文を作成
let newOrder = { order with OrderLines = newOrderLines }
// 5. 注文を返す
newOrder
サブエンティティ の 1 つ(OrderLine)を変更するだけであっても、常に Order 自体のレベルで作業する必要がある よく起こることなので、それぞれ名前が付いている
集約による整合性と不変条件の担保
集約 はデータが更新されたとき、整合性の境界として機能する 整合性の境界?
集約のある部分が更新されると、整合性を担保するために他の部分も更新する必要がある
e.g. トップレベルの Order に合計金額を追加で保存する
明細行の 1 つの価格が変更された場合、データの整合性を保つために合計も更新する
Order には少なくとも 1 つの OrderLine が存在すること
集約の参照
code:fsharp
type Order = {
OrderId : OrderId
Customer : Customer
OrderLines ; OrderLine list
}
イミュータブルの波及効果
Customer を更新したとき Order を更新する必要がある
代わりに参照(アイデンティティ)を格納すべき
code:fsharp
type Order = {
OrderId : OrderId
CustomerId : CustomerId
OrderLines ; OrderLine list
}
データベースからオブジェクトをロードまたはセーブしたい場合は、集約全体をロードまたはセーブすべき
オブジェクトをシリアライズする場合も同様
集約全体をシリアライズして、ネットワーク送信する
データベーストランザクションは、単一の集約を扱うべき
複数の集約を含んだり、集約の境界を超えてはならない
e.g. Customers (Customer のリスト)
エンティティの集まり
しかし、トップレベルのエンティティをルートに持たず、整合性の境界にもならないため集約ではない